package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.bean.Category;
import com.itheima.bean.Setmeal;
import com.itheima.bean.SetmealDish;
import com.itheima.common.PageParam;
import com.itheima.dao.SetmealDao;
import com.itheima.dto.SetmealDto;
import com.itheima.exception.CustomException;
import com.itheima.service.CategoryService;
import com.itheima.service.SetmealDishService;
import com.itheima.service.SetmealService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class SetmealServiceImpl implements SetmealService {

    @Autowired
    private SetmealDao setmealDao;

    @Autowired
    private SetmealDishService setmealDishService;

    @Lazy
    @Autowired
    private CategoryService categoryService;

    /**
     * 根据分类id和状态值来查询套餐
     *
     * @param categoryId
     * @param status
     * @return
     */
    @Override
    public List<Setmeal> findByCategoryId(Long categoryId, Integer status) {

        LambdaQueryWrapper<Setmeal> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Setmeal::getCategoryId , categoryId);
        lqw.eq(Setmeal::getStatus , status);

        return setmealDao.selectList(lqw);
    }

    /**
     * 删除套餐
     *  1. 删除套餐和以前的删除不一样，需要判定，如果套餐属于启售状态，那么禁止删除。
     *      1.1 拿着套餐的id，去查询套餐表，看看是否有套餐属于启售状态！
     *      1.2 如果没有，就可以删除。如果有，就禁止删除！
     *
     * @param ids
     * @return
     */
    @Override
    public int delete(List<Long> ids) {
        //1. 查询这一批id集合里面，是否有套餐属于启售状态！
        // select * from setmeal where id in (1, 3, 5) and status = 1

        //1.1 构建条件对象
        LambdaQueryWrapper<Setmeal> lqw = new LambdaQueryWrapper<>();

        //1.2 追加条件
        lqw.in(Setmeal::getId , ids);
        lqw.eq(Setmeal::getStatus , 1) ;// 设置状态值为启售

        //1.3 执行查询
        int count = setmealDao.selectCount(lqw);

        //1.4 如果数量 > 0 禁止它删除
        if (count >  0 ) {
            throw  new CustomException("套餐处于启售状态，禁止删除！");
        }

        //2. 如果程序运行到了这里，即表示套餐属于停售状态，那么直接删除即可
        return setmealDao.deleteBatchIds(ids);
    }

    /**
     * 套餐分页
     *
     * @param pageParam
     * @return
     */
    @Override
    public IPage<SetmealDto> findPage(PageParam pageParam) {

        //1. 构建分页对象
        IPage<Setmeal> p = new Page<>(pageParam.getPage() , pageParam.getPageSize());

        //2. 构建条件对象
        LambdaQueryWrapper<Setmeal> lqw = new LambdaQueryWrapper<>();

        //3. 追加条件
        lqw.like(pageParam.getName() != null , Setmeal::getName , pageParam.getName());

        //4. 执行查询
        IPage<Setmeal> setmealIPage = setmealDao.selectPage(p, lqw);


        //5. 遍历出来每一个套餐：
        List<SetmealDto> setmealDtoList = setmealIPage.getRecords().stream().map(setmeal -> {

            //5.1 拿着套餐的分类id去查询分类表，得到分类的数据
            Category category = categoryService.findById(setmeal.getCategoryId());

            //5.2 构建SetmealDto
            SetmealDto setmealDto = new SetmealDto();

            //5.3 封装分类数据到SetmealDto
            setmealDto.setCategoryName(category.getName());

            //5.4 封装套餐数据到SetmealDto
            BeanUtils.copyProperties(setmeal, setmealDto);

            //TODO:: 其实套餐数据，还需要封装该套餐拥有哪些菜品， 这样在更新页面上就可以回显了！

            //5.5 返回setmealDto 意思就是每一个setmeal 就映射出来一个setmealDto
            return setmealDto;

        }).collect(Collectors.toList());

        //6. 构建IPage<SetmealDto>
        IPage<SetmealDto> dtoIPage = new Page<>();

        //6.1 封装总记录数
        dtoIPage.setTotal(setmealIPage.getTotal());

        //6.2 封装集合数据
        dtoIPage.setRecords(setmealDtoList);

        //7. 返回
        return dtoIPage;


    }

    /**
     * 添加套餐
     *  1. 添加套餐和其他的添加不一样，因为它要操作两张表： setmeal 套餐表 和 setmeal_dish 套餐菜品表
     *      1.1 先往套餐表加数据
     *
     *      1.2 再往套餐菜品表加数据
     *
     * @param setmealDto
     * @return
     */
    @Override
    public int add(SetmealDto setmealDto) {

        //1. 先往套餐表加数据
        int row1 = setmealDao.insert(setmealDto);

        if(row1 > 0 ){
            //2. 再往套餐菜品表加数据
            List<SetmealDish> setmealDishList = setmealDto.getSetmealDishes();

            if(setmealDishList!=null && setmealDishList.size() > 0){
                int row2 = 0 ;
                //2.1 遍历每一个菜品数据
                for (SetmealDish setmealDish : setmealDishList) {

                    //2.2 设置套餐的id。
                    setmealDish.setSetmealId(setmealDto.getId());

                    //2.3 执行添加操作
                    row2 += setmealDishService.add(setmealDish);
                }
                return row2 == setmealDishList.size() ? 1 : 0;
            }
        }
        return row1;
    }

    /**
     * 根据分类的id来查询套餐数据
     *
     * @param categoryId
     * @return
     */
    @Override
    public List<Setmeal> findByCategoryId(Long categoryId) {

        //1. 构建条件对象
        LambdaQueryWrapper<Setmeal> lqw = new LambdaQueryWrapper<>();

        //2. 追加条件
        lqw.eq(Setmeal::getCategoryId , categoryId);

        //3. 执行查询
        return setmealDao.selectList(lqw);
    }
}
